/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/cat.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../msg_aio/head.h"
#include "../config/head.h"
#include "../macro/head.h"
#include "../impl/head.h"
#include "../msg/head.h"
#include "../impl/head.h"
#include "pkg_http.h"

namespace cat
{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 

	pkg_http::pkg_http()
	{
	}

	pkg_http::~pkg_http()
	{
	}

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// proc

	int pkg_http::proc( xos::i_msg *& pMsg )
	{
        int ret = 1;

        int nMsg = pMsg->get_int( 0, 0 );

        switch( nMsg )
        {
        case PACKET_HTTP_UN_PACKAGE_FLUSH:
            {
                flush( pMsg );
            }
            break;
        case PACKET_HTTP_UN_PACKAGE:
            {
                un_package( pMsg );
            }
            break;
        case PACKET_HTTP_PACKAGE:
            {
                package( pMsg );
            }
            break;
        default:
            {
                ret = 0;
            }
            break;
        }

        return ret;
	}

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int pkg_http::un_package( xos::i_msg *& pMsg )
    {
        int ret = 0;

        task * pTask = ( task * )pMsg->get_void( 0, 0 );
        connection * pConnect = pTask->m_pConnection;
        request * pRequest = pTask->m_pRequest;
        tcp * pTcp = pConnect->m_pTcp;

        if( ( 0 == ret ) && !pTcp->m_pParseRequest )
        {
            mgr::xos()->http()->create( xos_http::OBJ_PARSE_REQUEST, ( void** )&pTcp->m_pParseRequest );
        }

        if( ( 0 == ret ) && ( pRequest->m_pUnEnctyptList->size() == 0 ) )
        {
            ret = 1;
        }

        if( ( 0 == ret ) && !pTask->m_bRecving )
        {
            pConnect->set_timeout_time_s( config::get()->http_timeout_s );
            pTask->m_bRecving = true;
        }

        while( 0 == ret )
        {
            ret = parse_more( pConnect );
        }

        pTask->un_lock_server_for_request_data();
        LOG4( "un_package (%s:%d)(%s:%d)(%d)", pTcp->m_local_ip.c_str(), pTcp->m_nLocalPort, pTcp->m_peer_ip.c_str(), pTcp->m_nPeerPort, pConnect->m_nLockNum );

        if( 0 == ret )
        {
            if( pRequest->m_pUnEnctyptList->size() > 0 )
            {
                pConnect->set_timeout_time_s( config::get()->http_timeout_s );
            }
            else
            {
                pConnect->net_timeout_ms = 0;
                pTask->m_bRecving = false;
            }
        }

        if( ( ret < 0 ) && pConnect->running() )
        {
            pConnect->set_data_err();
            pConnect->lock_server();
            pMsg->set_void( 0, pConnect );
            pMsg->set_int( 0, NET_TCP_DATA_ERR );
            msg::notify_net( pMsg, false );
        }

        return ret;
    }

    int pkg_http::parse_more( connection * pConnect )
    {
        int ret = 0;

        task::T * pTask = pConnect->m_pTask;
        tcp * pTcp = pConnect->m_pTcp;
        request * pRequest = pTask->m_pRequest;
        xos_http::i_parse_request * pParse = pTcp->m_pParseRequest;

        if( 0 == ret )
        {
            pParse->set_param_property( pRequest->m_pParamProp );
            pParse->set_path_property( pRequest->m_pPathProp );
            pParse->set_tag_property( pRequest->m_pTagProp );
            pParse->set_body_list( pRequest->m_pUnPackageList );
            pParse->set_recv_list( pRequest->m_pUnEnctyptList );
            pParse->set_ssl( pConnect->ssl() );
        }

        if( 0 == ret )
        {
            ret = pParse->proc();
        }

        if( 0 == ret )
        {
            pParse->reset();
        }

        if( 0 == ret )
        {
            task * pT = task::init_task( pConnect, true );
            pT->swap_http_request( pTask );
            xos::i_msg * pMsg = mgr::xos()->msg();
            pMsg->set_void( 0, pT );
            msg::notify_package( pMsg, PACKET_HTTP_UN_COMPRESS, false );
            pT = 0;
        }

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int pkg_http::package( xos::i_msg *& pMsg )
    {
        int ret = 0;

        task * pTask = ( task* )pMsg->get_void( 0, 0 );
        connection * pConnect = pTask->m_pConnection;
        response * pResponse = pTask->m_pResponse;
        tcp * pTcp = pConnect->m_pTcp;
        xos_http::i_compose_return * pComposeRet = pTcp->m_pComposeRet;

        if( ( 0 == ret ) && !pComposeRet )
        {
            mgr::xos()->http()->create( xos_http::OBJ_COMPOSE_RETURN, ( void** )&pComposeRet );
            pTcp->m_pComposeRet = pComposeRet;
        }

        if( 0 == ret )
        {
            pComposeRet->set_tag_property( pResponse->m_pTagProp );
            pComposeRet->set_body_list( pResponse->m_pCompressList );
            pComposeRet->set_send_list( pResponse->m_pPackageList );
        }

        if( 0 == ret )
        {
            ret = pComposeRet->proc();
        }

        if( 0 == ret )
        {
            msg::notify_package( pMsg, PACKET_HTTP_ENCRYPT, false );
            pComposeRet->reset();
        }

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int pkg_http::flush( xos::i_msg *& pMsg )
    {
        int ret = 0;

        task * pTask = ( task * )pMsg->get_void( 0, 0 );
        request * pRequest = pTask->m_pRequest;

        pRequest->m_pUnCompressList->release_all();
        pRequest->m_pUnPackageList->release_all();
        pRequest->m_pUnEnctyptList->release_all();

        pTask->un_lock_server_for_request_data();

        msg::notify_package( pMsg, PACKET_HTTP_UN_COMPRESS_FLUSH, false );

        return ret;
    }

} // cat
